package test;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.time.DateUtils;
import org.mm.model.TherapyTask;
import org.mm.model.TherapyTaskEvent;
import org.mm.model.User;
import org.quartz.CronExpression;

public class CronExpressionDeveloper {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			CronExpressionDeveloper t = new CronExpressionDeveloper();
			List<Date> dates = t.test1();
			List<TherapyTaskEvent> events = t.buildTherapyTasksEvents(new Long(1), dates);
			if (events != null) {
				for (TherapyTaskEvent tte : events) {
					System.out.println(tte);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public List<TherapyTaskEvent> buildTherapyTasksEvents(Long therapyTaskId, List<Date> dates) throws Exception {
		List<TherapyTaskEvent> ttes = null;
		if (dates != null) {
			ttes = new ArrayList<TherapyTaskEvent>();
			long now = (new Date(System.currentTimeMillis())).getTime();
			long start = (DateUtils.parseDate("1980-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss")).getTime();
			for (Date d : dates) {
				//System.out.println("date=" + d);
				TherapyTaskEvent tte = new TherapyTaskEvent();
				tte.setTherapyTaskEventCreationDate(new Timestamp(now));
				tte.setTherapyTask(new TherapyTask(therapyTaskId));
				tte.setTherapyTaskEventScheduledDate(new Timestamp(d.getTime()));
//				tte.setTherapyTaskEventData(d);
				tte.setTherapyTaskEventExecutionDate(new Timestamp(start));
//				tte.setTherapyTaskEventNote("no note");
				tte.setTherapyTaskEventLastModificationDate(new Timestamp(now));
				tte.setUser1(new User(1l));
				tte.setUser2(new User(1l));
				ttes.add(tte);
				/*



	//bi-directional many-to-one association to Measurement
	@ManyToOne
	@JoinColumn(name="therapy_task_event_measurement_id")
	private Measurement measurement;
				 */

			}
		}
		return ttes;
	}

	/**
	 * lunedi, mercoledi, venerdi alle 21.00 per tutto maggio
	 */
	public List<Date> test1() throws Exception {
		// s m h dm m dw
		String expression = "0 0 21 ? * 2,4,6";
		Date startDate = DateUtils.parseDate("2013-05-01 00:00:00", "yyyy-MM-dd HH:mm:ss");
		Date endDate = DateUtils.parseDate("2013-05-31 23:59:59", "yyyy-MM-dd HH:mm:ss");
		List<Date> dates = testCronExpression(startDate, endDate, expression);
		return dates;
	}

	/**
	 * tutti i giorni alle 14.00 dal 15/05 al 15/06
	 */
	public List<Date> test2() throws Exception {
		// s m h dm m dw
		String expression = "0 0 14 ? * *";
		Date startDate = DateUtils.parseDate("2013-05-15", "yyyy-MM-dd");
		Date endDate = DateUtils.parseDate("2013-06-15", "yyyy-MM-dd");
		List<Date> dates = testCronExpression(startDate, endDate, expression);
		return dates;
	}

	/**
	 * domenica, martedi, giovedi, sabato alle 08.00 dal 20/06 al 10/07
	 */
	public List<Date> test3() throws Exception {
		// s m h dm m dw
		String expression = "0 0 8 ? * 1,3,5,7";
		Date startDate = DateUtils.parseDate("2013-06-20 00:00:00", "yyyy-MM-dd HH:mm:ss");
		Date endDate = DateUtils.parseDate("2013-07-10 23:59:59", "yyyy-MM-dd HH:mm:ss");
		List<Date> dates = testCronExpression(startDate, endDate, expression);
		return dates;
	}

	public List<Date> testCronExpression(Date startDate, Date endDate,
			String expression) throws Exception {
		List<Date> dates = null;
		boolean isValid = CronExpression.isValidExpression(expression);
		if (isValid) {
			dates = new ArrayList<Date>();
			CronExpression ce = new CronExpression(expression);
			/*Date date = startDate;*/
			Date calendarDate = startDate;
			long end = endDate.getTime();
			while (calendarDate.getTime() <= end) {
				calendarDate = ce.getNextValidTimeAfter(calendarDate);
				if (calendarDate.getTime() <= end) {
					addCalendarDate(dates, calendarDate);
				}
				calendarDate = DateUtils.addMinutes(calendarDate, 1);
			}

		}
		return dates;

	}

	public void addCalendarDate(List<Date> dates, Date calendarDate) {
		Iterator<Date> iterator = dates.iterator();
		boolean isFound = false;
		while (iterator.hasNext() && !isFound) {
			isFound = DateUtils.isSameInstant(calendarDate, iterator.next());
		}
		if (!isFound) {
			dates.add(calendarDate);
		}
	}



}
